P2444 [POI2000]病毒
这道题直接输出都可以得60分,如果再写个随机算法,那么就可以用O(1)的时间复杂度解决这道题
首先看到这到题,不难想到暴力去枚举每一位,然后再用AC自动机,因为每个点最多只会被访问一次,所以时间复杂度可以道玄学的O(n)
代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<queue>
using namespace std;
const int N = 1e5 + 5;

char str[N];
int tr[N][2], cnt[N], net[N], idx;
bool vis[N];
queue<int> q;

void insert()
{
int p = 0;
for (int i = 0; str[i]; i++)
{
int t = str[i] - '0';
if (!tr[p][t])
tr[p][t] = ++idx;
p = tr[p][t];
}
cnt[p] = 1;
}

void build()
{
if (tr[0][0])
q.push(tr[0][0]);
if (tr[0][1])
q.push(tr[0][1]);
while (!q.empty())
{
int t = q.front();
q.pop();
for (int i = 0; i < 2; i++)
{
int p = tr[t][i];
if (!p)
tr[t][i] = tr[net[t]][i];
else
{
net[p] = tr[net[t]][i];
q.push(p);
}
}
}
}

void dfs(int j)
{
for (int i = 0; i < 2; i++)
{
bool flag = false;
int t = tr[j][i];
if (vis[t])
{
printf("TAK");
exit(0);
}
while (t)
{
if (cnt[t])
flag = true;
t = net[t];
}
if (!flag)
{
vis[tr[j][i]] = true;
dfs(tr[j][i]);
vis[tr[j][i]] = false;
}
}
}

int main()
{
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%s", &str);
insert();
}
build();
dfs(0);
printf("NIE");
return 0;
}